﻿using System;
using System.Collections.Generic;
using System.Text;
using System.DirectoryServices;
using System.Reflection;

namespace IISAdmin
{
    public class Site
    {
        public enum SiteStatus
        {
            Starting = 1,
            Started = 2,
            Stopping = 3,
            Stopped = 4,
            Pausing = 5,
            Paused = 6,
            Continuing = 7
        }

        private ServerManager ServerManager { get; set; }
        private DirectoryEntry DirectoryEntry { get; set; }
        private DirectoryEntry DirectoryEntryRoot { get; set; }

        internal Site(DirectoryEntry DirectoryEntry, ServerManager ServerManager)
        {
            this.ServerManager = ServerManager;
            this.DirectoryEntry = DirectoryEntry;
            this.DirectoryEntryRoot = new DirectoryEntry(this.ADsPath + "/ROOT");
        }

        internal string ADsPath { get { return DirectoryEntry.Path; } }

        public void CommitChanges() { this.DirectoryEntry.CommitChanges(); }

        public string ID { get { return DirectoryEntry.Name; } }

        #region Properties
        public System.Int32 AccessFlags { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AccessFlags"].Value; } }

        public System.Int32 AppIsolated { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AppIsolated"].Value; } }

        public System.String AppFriendlyName { get { return (System.String)this.DirectoryEntryRoot.Properties["AppFriendlyName"].Value; } }

        public System.String AppPoolId { get { return (System.String)this.DirectoryEntryRoot.Properties["AppPoolId"].Value; } }

        public System.String AppRoot { get { return (System.String)this.DirectoryEntryRoot.Properties["AppRoot"].Value; } }

        public System.String KeyType { get { return (System.String)this.DirectoryEntryRoot.Properties["KeyType"].Value; } }

        public System.String Path { get { return (System.String)this.DirectoryEntryRoot.Properties["Path"].Value; } }

        public System.String DefaultDoc { get { return (System.String)this.DirectoryEntryRoot.Properties["DefaultDoc"].Value; } }

        public System.Boolean AppAllowClientDebug { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AppAllowClientDebug"].Value; } }

        public System.Boolean AppAllowDebugging { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AppAllowDebugging"].Value; } }

        public System.Boolean AspAllowOutOfProcComponents { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspAllowOutOfProcComponents"].Value; } }

        public System.Boolean AspAllowSessionState { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspAllowSessionState"].Value; } }

        public System.Int32 AspAppServiceFlags { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspAppServiceFlags"].Value; } }

        public System.Int32 AspBufferingLimit { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspBufferingLimit"].Value; } }

        public System.Boolean AspBufferingOn { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspBufferingOn"].Value; } }

        public System.Boolean AspCalcLineNumber { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspCalcLineNumber"].Value; } }

        public System.Int32 AspCodepage { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspCodepage"].Value; } }

        public System.Boolean AspEnableApplicationRestart { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspEnableApplicationRestart"].Value; } }

        public System.Boolean AspEnableAspHtmlFallback { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspEnableAspHtmlFallback"].Value; } }

        public System.Boolean AspEnableChunkedEncoding { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspEnableChunkedEncoding"].Value; } }

        public System.Boolean AspEnableParentPaths { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspEnableParentPaths"].Value; } }

        public System.Boolean AspEnableTypelibCache { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspEnableTypelibCache"].Value; } }

        public System.Boolean AspErrorsToNTLog { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspErrorsToNTLog"].Value; } }

        public System.Boolean AspExceptionCatchEnable { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspExceptionCatchEnable"].Value; } }

        public System.Int32 AspExecuteInMTA { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspExecuteInMTA"].Value; } }

        public System.Int32 AspKeepSessionIDSecure { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspKeepSessionIDSecure"].Value; } }

        public System.Int32 AspLCID { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspLCID"].Value; } }

        public System.Boolean AspLogErrorRequests { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspLogErrorRequests"].Value; } }

        public System.Int32 AspMaxDiskTemplateCacheFiles { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspMaxDiskTemplateCacheFiles"].Value; } }

        public System.Int32 AspMaxRequestEntityAllowed { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspMaxRequestEntityAllowed"].Value; } }

        public System.Int32 AspProcessorThreadMax { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspProcessorThreadMax"].Value; } }

        public System.Int32 AspQueueConnectionTestTime { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspQueueConnectionTestTime"].Value; } }

        public System.Int32 AspQueueTimeout { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspQueueTimeout"].Value; } }

        public System.Int32 AspRequestQueueMax { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspRequestQueueMax"].Value; } }

        public System.Boolean AspRunOnEndAnonymously { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspRunOnEndAnonymously"].Value; } }

        public System.Int32 AspScriptEngineCacheMax { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspScriptEngineCacheMax"].Value; } }

        public System.Boolean AspScriptErrorSentToBrowser { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspScriptErrorSentToBrowser"].Value; } }

        public System.Int32 AspScriptFileCacheSize { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspScriptFileCacheSize"].Value; } }

        public System.Int32 AspScriptTimeout { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspScriptTimeout"].Value; } }

        public System.Int32 AspSessionMax { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspSessionMax"].Value; } }

        public System.Int32 AspSessionTimeout { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AspSessionTimeout"].Value; } }

        public System.Boolean AspTrackThreadingModel { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["AspTrackThreadingModel"].Value; } }

        public System.Int32 AuthFlags { get { return (System.Int32)this.DirectoryEntryRoot.Properties["AuthFlags"].Value; } }

        public System.Boolean CacheISAPI { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["CacheISAPI"].Value; } }

        public System.Int32 CGITimeout { get { return (System.Int32)this.DirectoryEntryRoot.Properties["CGITimeout"].Value; } }

        public System.Boolean ContentIndexed { get { return (System.Boolean)this.DirectoryEntryRoot.Properties["ContentIndexed"].Value; } }

        public System.Int32 DirBrowseFlags { get { return (System.Int32)this.DirectoryEntryRoot.Properties["DirBrowseFlags"].Value; } }

        public System.Int32 PasswordChangeFlags { get { return (System.Int32)this.DirectoryEntryRoot.Properties["PasswordChangeFlags"].Value; } }

        public System.String AnonymousUserName { get { return (System.String)this.DirectoryEntryRoot.Properties["AnonymousUserName"].Value; } }

        public System.String AnonymousUserPass { get { return (System.String)this.DirectoryEntryRoot.Properties["AnonymousUserPass"].Value; } }

        public System.String AspScriptErrorMessage { get { return (System.String)this.DirectoryEntryRoot.Properties["AspScriptErrorMessage"].Value; } }

        public System.String AspScriptLanguage { get { return (System.String)this.DirectoryEntryRoot.Properties["AspScriptLanguage"].Value; } }

        public System.String AuthChangeURL { get { return (System.String)this.DirectoryEntryRoot.Properties["AuthChangeURL"].Value; } }

        public System.String AuthExpiredUnsecureURL { get { return (System.String)this.DirectoryEntryRoot.Properties["AuthExpiredUnsecureURL"].Value; } }

        public System.String AuthExpiredURL { get { return (System.String)this.DirectoryEntryRoot.Properties["AuthExpiredURL"].Value; } }

        public System.String AuthNotifyPwdExpUnsecureURL { get { return (System.String)this.DirectoryEntryRoot.Properties["AuthNotifyPwdExpUnsecureURL"].Value; } }

        public System.String AuthNotifyPwdExpURL { get { return (System.String)this.DirectoryEntryRoot.Properties["AuthNotifyPwdExpURL"].Value; } }

        public System.String AspDiskTemplateCacheDirectory { get { return (System.String)this.DirectoryEntryRoot.Properties["AspDiskTemplateCacheDirectory"].Value; } }

        public System.String HttpCustomHeaders { get { return (System.String)this.DirectoryEntryRoot.Properties["HttpCustomHeaders"].Value; } }

        public System.Object[] HttpErrors { get { return (System.Object[])this.DirectoryEntryRoot.Properties["HttpErrors"].Value; } }

        public System.Object[] ScriptMaps { get { return (System.Object[])this.DirectoryEntryRoot.Properties["ScriptMaps"].Value; } }
       
        public System.Int32 ServerSize { get { return (System.Int32)this.DirectoryEntry.Properties["ServerSize"].Value; } }

        public System.Int32 ServerState { get { return (System.Int32)this.DirectoryEntry.Properties["ServerState"].Value; } }

        public System.Int32 Win32Error { get { return (System.Int32)this.DirectoryEntry.Properties["Win32Error"].Value; } }

        public System.String ServerComment { get { return (System.String)this.DirectoryEntry.Properties["ServerComment"].Value; } }

        public System.String ServerBindings { get { return (System.String)this.DirectoryEntry.Properties["ServerBindings"].Value; } }

        public System.Boolean AllowKeepAlive { get { return (System.Boolean)this.DirectoryEntry.Properties["AllowKeepAlive"].Value; } }

        public System.Int32 ConnectionTimeout { get { return (System.Int32)this.DirectoryEntry.Properties["ConnectionTimeout"].Value; } }
        
        public System.Int32 LogExtFileFlags { get { return (System.Int32)this.DirectoryEntry.Properties["LogExtFileFlags"].Value; } }

        public System.Int32 LogFilePeriod { get { return (System.Int32)this.DirectoryEntry.Properties["LogFilePeriod"].Value; } }

        public System.Int32 LogFileTruncateSize { get { return (System.Int32)this.DirectoryEntry.Properties["LogFileTruncateSize"].Value; } }

        public System.Int32 LogType { get { return (System.Int32)this.DirectoryEntry.Properties["LogType"].Value; } }

        public System.Int32 MaxConnections { get { return (System.Int32)this.DirectoryEntry.Properties["MaxConnections"].Value; } }
        
        public System.String LogOdbcDataSource { get { return (System.String)this.DirectoryEntry.Properties["LogOdbcDataSource"].Value; } }

        public System.String LogOdbcPassword { get { return (System.String)this.DirectoryEntry.Properties["LogOdbcPassword"].Value; } }

        public System.String LogOdbcTableName { get { return (System.String)this.DirectoryEntry.Properties["LogOdbcTableName"].Value; } }

        public System.String LogOdbcUserName { get { return (System.String)this.DirectoryEntry.Properties["LogOdbcUserName"].Value; } }

        public System.String LogPluginClsid { get { return (System.String)this.DirectoryEntry.Properties["LogPluginClsid"].Value; } }

        public System.String LogFileDirectory { get { return (System.String)this.DirectoryEntry.Properties["LogFileDirectory"].Value; } }
        
        public System.Int32 MaxBandwidth { get { return (System.Int32)this.DirectoryEntry.Properties["MaxBandwidth"].Value; } }

        //public AdminACL AdminACL { get { return (AdminACL)this.DirectoryEntry.Properties["AdminACL"].Value; } }
        #endregion


        /// <summary>
        /// Resumes the server.
        /// </summary>
        public void Continue()
        {
            using (DirectoryEntry iisSite = new DirectoryEntry(this.ADsPath))
            {
                iisSite.Invoke("Continue",
                    new object[0]);
            }
        }

        /// <summary>
        /// Pauses the server.
        /// </summary>
        public void Pause() { }

        /// <summary>
        /// Starts the server.
        /// </summary>
        public void Start()
        {
            using (DirectoryEntry iisSite = new DirectoryEntry(this.ADsPath))
            {
                iisSite.Invoke("Start",
                    new object[0]);
            }
        }

        /// <summary>
        /// Retrieves the current status of the server.
        /// </summary>
        public SiteStatus Status
        {
            get
            {
                Int32 status = 4;
                using (DirectoryEntry iisSite = new DirectoryEntry(this.ADsPath))
                {
                    Object ads = iisSite.NativeObject;
                    Type type = ads.GetType();
                    status = (Int32)type.InvokeMember("Status",
                                                           BindingFlags.GetProperty,
                                                           null, ads, null);

                    //Int32 Status = (Int32)iisSite.Invoke("Status",
                    //    new object[0]);
                }
                return (SiteStatus)status;
            }
        }

        /// <summary>
        /// Stops the server.
        /// </summary>
        public void Stop()
        {
            using (DirectoryEntry iisSite = new DirectoryEntry(this.ADsPath))
            {
                iisSite.Invoke("Stop",
                    new object[0]);
            }
        }

    }
}
